namespace Fftw
{
    using System;
    using System.Runtime.InteropServices;
    
    public class PlanRealToComplex3D : Plan
    {
        [DllImport ("libfftw3")]
        private static extern IntPtr fftw_plan_dft_r2c_3d(int nx, int ny, int nz, double[] in_data, Complex[] out_data, uint flags);
        
        [DllImport ("libfftw3")]
        private static extern void fftw_destroy_plan(IntPtr plan);
        
        private int n, nx, ny, nz;
        
        public PlanRealToComplex3D(int nx, int ny, int nz, double[] in_data, uint flags)
        {
            this.in_data_real = in_data;
            this.flags = flags;
            this.raw = IntPtr.Zero;
            this.nx = nx;
            this.ny = ny;
            this.nz = nz;
            this.n = nx * ny * nz;
            
            int ncomplex = nx * ny * (nz/2 + 1);
            if (in_data.Length < n)
                throw new FftwException(String.Format("Real input data (length = {0}) is not large enough for a {1} X {2} X {3} DFT", in_data.Length, nx, ny, nz));
            
            out_data = new Complex[ncomplex];
            
            CreatePlan();
        }
        
        ~PlanRealToComplex3D()
        {
            fftw_destroy_plan(raw);
        }
        
        protected override void CreatePlan()
        {
            raw = fftw_plan_dft_r2c_3d(nx, ny, nz, in_data_real, out_data, flags);
        }
    }
}
